﻿/*
 * @author: wizardc
 */

using System.Collections.Generic;
using DG.Tweening;
using Dou.Extend;
using Dou.Resource;
using UnityEngine;

namespace Dou.Audio
{
    /// <summary>
    /// 音频管理器
    /// </summary>
    public class AudioManager
    {
        private static AudioManager _instance;
        public static AudioManager instance => _instance ??= new AudioManager();
        
        private GameObject _root;
        private AudioListener _audioListener;
        
        private Dictionary<int, AudioController> _audioControllers = new Dictionary<int, AudioController>();
        
        private AudioController _bgMusic1;
        private AudioController _bgMusic2;
        private string _bgMusicAssetName;
        private bool _inFade = false;
        private Tweener _bgMusic1Tweener;
        private Tweener _bgMusic2Tweener;
        
        private AudioManager()
        {
        }

        /// <summary>
        /// 获取音频监听器
        /// </summary>
        public AudioListener audioListener => _audioListener;
        
        /// <summary>
        /// 初始化
        /// </summary>
        public void Init()
        {
            _root = new GameObject("AudioManage");
            GameObject.DontDestroyOnLoad(_root);
            _audioListener = _root.GetOrAddComponent<AudioListener>();
            
            // 注册默认的背景音乐
            _bgMusic1 = RegisterAudio(-1, "BGMusic1");
            _bgMusic2 = RegisterAudio(-1, "BGMusic2");
        }

        /// <summary>
        /// 注册一个音频对象
        /// </summary>
        public AudioController RegisterAudio(int id, string name, float panStereo = 0, float pitch = 1, float spatialBlend = 0)
        {
            var go = new GameObject(name);
            go.transform.SetParent(_root.transform, false);
            var audioSource = go.AddComponent<AudioSource>();
            audioSource.panStereo = panStereo;
            audioSource.pitch = pitch;
            audioSource.spatialBlend = spatialBlend;
            var audioController = go.AddComponent<AudioController>();
            if (id >= 0)
            {
                _audioControllers.Add(id, audioController);
            }
            return audioController;
        }

        /// <summary>
        /// 设置背景是否静音
        /// </summary>
        public void SetBGMute(bool mute)
        {
            _bgMusic1.mute = mute;
            _bgMusic2.mute = mute;
        }

        /// <summary>
        /// 获取背景是否静音
        /// </summary>
        public bool GetBGMute()
        {
            return _bgMusic1.mute;
        }

        /// <summary>
        /// 设置背景音量
        /// </summary>
        public void SetBGVolume(float volume)
        {
            _bgMusic1.volume = volume;
            _bgMusic2.volume = volume;
        }

        /// <summary>
        /// 获取背景音量
        /// </summary>
        public float GetBGVolume()
        {
            return _bgMusic1.volume;
        }
        
        /// <summary>
        /// 播放背景音乐
        /// 同一时刻只有一个背景音乐在播放
        /// </summary>
        public void PlayBG(string assetName, float fadeTime = 0)
        {
            if (_bgMusicAssetName == assetName)
            {
                return;
            }
            _bgMusicAssetName = assetName;
            
            if (_inFade)
            {
                KillBGFade();
            }

            if (fadeTime > 0)
            {
                (_bgMusic1, _bgMusic2) = (_bgMusic2, _bgMusic1); // 交换
                _bgMusic1.assetName = assetName;
                _bgMusic1.Play(true);
                _bgMusic1.volume = 0;
                _bgMusic1Tweener = DOTween.To(() => _bgMusic1.volume, x => _bgMusic1.volume = x, GetBGVolume(), fadeTime)
                    .OnComplete(() =>
                    {
                        _bgMusic2.assetName = null;
                        KillBGFade();
                    });
                _bgMusic2Tweener = DOTween.To(() => _bgMusic2.volume, x => _bgMusic2.volume = x, 0, fadeTime);
                _inFade = true;
            }
            else
            {
                _bgMusic1.assetName = assetName;
                _bgMusic1.Play(true);
                _bgMusic2.assetName = null;
            }
        }

        private void KillBGFade()
        {
            if (_bgMusic1Tweener != null)
            {
                _bgMusic1Tweener.Kill();
                _bgMusic1Tweener = null;
            }
            if (_bgMusic2Tweener != null)
            {
                _bgMusic2Tweener.Kill();
                _bgMusic2Tweener = null;
            }
            _inFade = false;
        }

        /// <summary>
        /// 暂停背景音乐
        /// </summary>
        public void PauseBG()
        {
            _bgMusic1Tweener?.Pause();
            _bgMusic1.Pause();
            _bgMusic2Tweener?.Pause();
            _bgMusic2.Pause();
        }

        /// <summary>
        /// 恢复背景音乐
        /// </summary>
        public void ResumeBG()
        {
            _bgMusic1Tweener?.Play();
            _bgMusic1.Resume();
            _bgMusic2Tweener?.Play();
            _bgMusic2.Resume();
        }

        /// <summary>
        /// 停止背景音乐
        /// </summary>
        public void StopBG()
        {
            KillBGFade();
            _bgMusic1.Stop();
            _bgMusic2.Stop();
        }

        /// <summary>
        /// 停止背景音乐播放并清理资源
        /// </summary>
        public void ClearBG()
        {
            _bgMusic1.assetName = null;
            _bgMusic2.assetName = null;
        }

        private bool GetSound(int id, out AudioController audioController)
        {
            return _audioControllers.TryGetValue(id, out audioController);
        }
        
        /// <summary>
        /// 设置音效静音
        /// </summary>
        public void SetSoundMute(int id, bool mute)
        {
            if (GetSound(id, out AudioController audioController))
            {
                audioController.mute = mute;
            }
        }

        /// <summary>
        /// 获取音效静音
        /// </summary>
        public bool GetSoundMute(int id)
        {
            if (GetSound(id, out AudioController audioController))
            {
                return audioController.mute;
            }
            return false;
        }
        
        /// <summary>
        /// 设置音效音量
        /// </summary>
        public void SetSoundVolume(int id, float volume)
        {
            if (GetSound(id, out AudioController audioController))
            {
                audioController.volume = volume;
            }
        }

        /// <summary>
        /// 获取音效音量
        /// </summary>
        public float GetSoundVolume(int id)
        {
            if (GetSound(id, out AudioController audioController))
            {
                return audioController.volume;
            }
            return 1;
        }
        
        /// <summary>
        /// 播放音效
        /// 同一时刻可以有多个不同 ID 的音效在播放，但是相同 ID 只有一个音效在播放
        /// </summary>
        public void PlaySound(int id, string assetName, bool isLoop = false, float time = 0)
        {
            if (GetSound(id, out AudioController audioController))
            {
                audioController.assetName = assetName;
                audioController.Play(isLoop, time);
            }
        }

        /// <summary>
        /// 暂停音效
        /// </summary>
        public void PauseSound(int id)
        {
            if (GetSound(id, out AudioController audioController))
            {
                audioController.Pause();
            }
        }

        /// <summary>
        /// 恢复音效
        /// </summary>
        public void ResumeSound(int id)
        {
            if (GetSound(id, out AudioController audioController))
            {
                audioController.Resume();
            }
        }

        /// <summary>
        /// 停止音效
        /// </summary>
        public void StopSound(int id)
        {
            if (GetSound(id, out AudioController audioController))
            {
                audioController.Stop();
            }
        }

        /// <summary>
        /// 停止音效并清理资源
        /// </summary>
        public void ClearSound(int id)
        {
            if (GetSound(id, out AudioController audioController))
            {
                audioController.assetName = null;
            }
        }

        /// <summary>
        /// 播放一个不受控制的短音效
        /// </summary>
        public void PlayOneShot(string assetName, float volume = 1.0f)
        {
            AssetManager.instance.LoadAsset(assetName, asset =>
            {
                var clip = asset as AudioClip;
                if (clip != null)
                {
                    _bgMusic2.audioSource.PlayOneShot(clip, volume);
                }
                AssetManager.instance.UnloadAsset(assetName);
            });
        }

        /// <summary>
        /// 设置所有音效静音
        /// </summary>
        public void SetAllSoundMute(bool mute)
        {
            foreach (var kv in _audioControllers)
            {
                var audioController = kv.Value;
                audioController.mute = mute;
            }
        }

        /// <summary>
        /// 设置所有音效音量
        /// </summary>
        public void SetAllSoundVolume(float volume)
        {
            foreach (var kv in _audioControllers)
            {
                var audioController = kv.Value;
                audioController.volume = volume;
            }
        }

        /// <summary>
        /// 暂停所有音效
        /// </summary>
        public void PauseAllSounds()
        {
            foreach (var kv in _audioControllers)
            {
                var audioController = kv.Value;
                audioController.Pause();
            }
        }

        /// <summary>
        /// 恢复所有音效
        /// </summary>
        public void ResumeAllSounds()
        {
            foreach (var kv in _audioControllers)
            {
                var audioController = kv.Value;
                audioController.Resume();
            }
        }

        /// <summary>
        /// 停止所有音效
        /// </summary>
        public void StopAllSounds()
        {
            foreach (var kv in _audioControllers)
            {
                var audioController = kv.Value;
                audioController.Stop();
            }
        }

        /// <summary>
        /// 停止所有音效并清理资源
        /// </summary>
        public void ClearAllSounds()
        {
            foreach (var kv in _audioControllers)
            {
                var audioController = kv.Value;
                audioController.assetName = null;
            }
        }
    }
}
